from jira import JIRA, Issue
import re

import datetime

def logprint(*args, sep=' ', end='\n'):
    print(datetime.datetime.now(),*args, sep=' ', end='\n')

AS_TYPE_FS1TA='FS1TA'
AS_TYPE_CP1='CP1'
AS_TYPE_CP2='CP2'

WORK_TYPE_FS1TA='FS1TA'
WORK_TYPE_CP1='CP1'
WORK_TYPE_CP2='CP2'
WORK_TYPE_SUB='SUB'

SPEC_TYPE_FS1TA='Pre-analysis'
SPEC_TYPE_CP1='CP1'
SPEC_TYPE_CP2='CP2'

ACTIVITY_TYPE_FS1TA='Pre-analysis'
ACTIVITY_TYPE_SFS='System Specification'

ISSUE_TYPE_FT_S='FT'
ISSUE_TYPE_SI_S='SI'
ISSUE_TYPE_EI_S='EI'
ISSUE_TYPE_CA_S='CA'

ISSUE_TYPE_FT_L='Customer Feature'
ISSUE_TYPE_SI_L='System Item'
ISSUE_TYPE_EI_L='Entity Item'
ISSUE_TYPE_CA_L='Competence Area'

DOMAIN_LIST=[
    'OAM',
    'OAM-Sync',
    'OAM-Security',
    'OSS',
    'Cloud',
    'Transport',
    'RRM_CP',
    'RRM_UP',
    'SiSo',
    'SiSo_RU',
    'RRM_AirPhone',
    'RRM_Airphone',
    'SiSo_AirPhone',
    'SiSo_Airphone',
    'Airphone',
    'Transport-Security',
    'Small Cell',
    'Performance & Capacity',
    'CallHandling',
    'QoSEndUserExp',
    'RadioPerf',
    'PerfCapa',
    'E2EOperability-Basic',
    'E2EOperability-Sec',
    'E2EOperability-Sync',
    'E2EOperability-RNL',
    'E2ETrs-Basic',
    'E2ETrs-Sec',
    'BB_HWI',
    'RU_HWI',
    'SmallCells'
]

DOMAIN_CA_MAP={
    'OAM':          '5GRAN SysSpecs OAM-BTS/OSS',
    'OSS':          '5GRAN SysSpecs OAM-BTS/OSS',
    'OAM-Sync':     '5GRAN SysSpecs OAM-Synch',
    'OAM-Security': '5GRAN SysSpecs OAM-Security',
    'Cloud':        '5GRAN SysSpecs Cloud',
    'Transport':    '5GRAN SysSpecs TRS',
    'SC':           'SC SFS',
    'RRM_CP':       '5GRAN SysSpecs CP',
    'RRM_UP':       '5GRAN SysSpecs UP',
    'SiSo':         '5GRAN SysSpecs Siso',
    'SiSo_RU':      '5GRAN SysSpecs RU',
    'L1':           '5GRAN SysSpecs UP L1',
    'Airphone':     '5GRAN SysSpecs AirPhone',
    'RRM_Airphone':  '5GRAN SysSpecs AirPhone',
    'RRM_AirPhone':  '5GRAN SysSpecs AirPhone',
    'SiSo_Airphone':  '5GRAN SysSpecs AirPhone',
    'SiSo_AirPhone':  '5GRAN SysSpecs AirPhone',
    'Transport-Security': '5GRAN SysSpecs TRS',
    'Small Cell':     'SC SFS',
    'Performance & Capacity':  '5GRAN SysSpecs UP'
}

DOMAIN_CA_MAP_S={
    'OAM':          'OAM-BTS/OSS',
    'OSS':          'OAM-BTS/OSS',
    'OAM-Sync':     'OAM-Synch',
    'OAM-Security': 'OAM-Security',
    'Cloud':        'Cloud',
    'Transport':    'TRS',
    'SC':           'SC',
    'Small Cell':   'SC',
    'RRM_CP':       'CP',
    'RRM_UP':       'UP',
    'SiSo':         'Siso',
    'SiSo_RU':      'RU',
    'L1':           'UP L1',
    'Airphone':     'AirPhone',
    'RRM_Airphone':  'AirPhone',
    'RRM_AirPhone':  'AirPhone',
    'SiSo_AirPhone': 'AirPhone',
    'Transport-Security': 'TRS',
    'Performance & Capacity': "PC"
}

issue_field_list = {
    'summary':           'Summary',
    'status':            'Status',
    'assignee':          'Assignee',
    'timespent':         'Time Spent',
    'issuetype':         'Issue Type',
    'issuelinks':        'Linked Issues',
    'customfield_14694': 'Original Estimate',
    'customfield_37381': 'Feature ID',
    'customfield_38690': 'Competence Area',
    'customfield_38693': 'End FB',
    'customfield_38694': 'Start FB',
    'customfield_31591': 'Target end',
    'customfield_38695': 'Feature Project Owner',
    'customfield_38698': 'Contact Person',
    'customfield_38702': 'Item ID',
    'customfield_38705': 'FS Status and Dates',
    'customfield_38710': 'Target Releases',
    'customfield_38712': 'Requirement Area',
    'customfield_38724': 'Planned System Release',
    'customfield_38728': 'Release Committed Status',
    'customfield_38738': 'System Spec Start FB',
    'customfield_38739': 'System Spec End FB',
    'customfield_38740': 'Entity Spec Start FB',
    'customfield_38741': 'Entity Spec End FB',
    'customfield_38744': 'Entity Test Start FB',
    'customfield_38745': 'Entity Test End FB',
    'customfield_38746': 'SW Start FB',
    'customfield_38747': 'SW End FB',
    'customfield_38750': 'Activity Type',
    'customfield_38753': 'sub-activity type',
    'customfield_38764': 'NIDD Impact',
    'customfield_39190': 'Σ Logged Effort',
    'customfield_39191': 'Σ Original Estimate',
    'customfield_39390': 'Object Model Expected in FB',
    'customfield_39590': 'Object Model Param Status',
    'customfield_39591': 'Object Model Counter Status',
    'customfield_39592': 'Object Model Fault Status',
    'customfield_43891': 'Requirement Area Owner',
    'aggregatetimespent':       'Σ Time Spent',
    'aggregatetimeestimate':    'Σ Remaining Estimate',
    'aggregatetimeoriginalestimate': 'Σ Original Estimate',
    'timeoriginalestimate':     'Original Estimate'
}

def init_jira_connection():
    url, user, passwd = readConfig()
    jira_obj = JIRA(server=url, auth=(user, passwd))
    return jira_obj

def getNumOfChilds(issue:Issue):
    n = 0
    for issueLinked in issue.fields.issuelinks:
        if (str(issueLinked.type) == 'Parent') & hasattr(issueLinked, 'outwardIssue'):
            n = n + 1
    return n

def getChildItems(jira:JIRA, issue:Issue):
    childs=[]
    for issueLinked in issue.fields.issuelinks:
        if (str(issueLinked.type) == 'Parent') and hasattr(issueLinked, 'outwardIssue'):
            child = jira.issue(issueLinked.outwardIssue.key)
            childs.append(child)
    return childs

def parseFeatureTitle(issue:Issue):
    if issue.fields.issuetype.name != ISSUE_TYPE_FT_L:
        raise Exception("Given Issue is not a Customer Feature", issue.fields.issuetype)

    summary=issue.fields.summary
    reobj=re.compile('^(5GC00[0-9]{4}) (.*)')
    match=reobj.search(summary)
    if not match:
        raise Exception("Unrecognized feature", summary)
    elif len(match.groups()) != 2:
        raise Exception("Unrecognized feature", summary)
    return match.group(1),match.group(2)

def parseSubFeatureSysItem(issue:Issue):
    if issue.fields.issuetype.name != ISSUE_TYPE_SI_L:
        raise Exception("Given Issue is not a System Item", issue.fields.issuetype)

    summary=issue.fields.summary
    reobj=re.compile('^(5GC00[0-9]{4})-([A-Y])- (.*)')
    match=reobj.search(summary)
    if match:
        return match.groups()
    else:
        return None

def createNameForSubFeature(feature:str, title:str, subFeature:str):
    name = ''
    if (not type) or (not feature) or (not title):
        raise Exception("Empty fileds", 'FEATURE:"%s", TITLE:"%s", SUB-FEATURE:"%s"'%(feature, title, subFeature))
    name="%s-%s- %s"%(feature,subFeature,title)
    return name

def createItemIdForSubFeature(issuetype:str, feature:str,subFeature:str):
    name = ''
    if (not issuetype) or (not feature) or (not subFeature):
        raise Exception("Empty fileds", 'FEATURE:"%s", ISSUE_TYPE:"%s", SUB-FEATURE:"%s"'%(feature, issuetype, subFeature))
    name="%s-%s-%s"%(feature, subFeature, issuetype)
    return name

def getCustomerFeatureViaId(jira:JIRA, feature_id:str):
    jql='type = "Customer Feature" AND summary ~ '+feature_id
    issueList = jira.search_issues(jql, maxResults=0,validate_query=True, fields=getFieldList())
    if not issueList:
        raise Exception('Invalid feature ID', feature_id)
    elif len(issueList) > 1:
        raise Exception('Existing duplicated items', (issueList[0].key, issueList[1].key))
    return issueList[0]

def readConfig():
    import configparser
    config = configparser.ConfigParser()
    config.read_file(open(getConfigFile()))

    return config.get('Account', 'url'), config.get('Account', 'user'), config.get('Account', 'passwd')

def getConfigFile():
    import platform
    import os
    if platform.system() == "Windows":
         file = os.path.split(os.path.abspath(__file__))[0] +"\config.ini"
    else:
         file = os.path.split(os.path.abspath(__file__))[0] +'/config.ini'

    return file

def getNiddTasks():
    import configparser
    config = configparser.ConfigParser()
    config.read_file(open(getConfigFile()))
    nidd_tasks=[]

    for section in config:
        if section.find("NIDD") >= 0:
            nidd_tasks.append(section)
    return nidd_tasks

def getTask(task):
    import configparser
    config = configparser.ConfigParser()
    config.read_file(open(getConfigFile()))

    return config.get(task, 'JQL'), config.get(task, "File")

def getCfamLeaderListFile():
    import configparser
    config = configparser.ConfigParser()
    config.read_file(open(getConfigFile()))

    return config.get('CFAM_Leader', 'File')

def getCfamStatusFile():
    import configparser
    config = configparser.ConfigParser()
    config.read_file(open(getConfigFile()))

    return config.get('CFAM_Status', 'File')

def getStatus(issue:Issue):
    return str(issue.fields.status.name)

def get_issue_status(issue:Issue):
    if not hasattr(issue.fields, 'status'):
        raise Exception("No status field, add status in field list", issue.key)
    return str(issue.fields.status.name)

def get_summary(issue:Issue):
    if not hasattr(issue.fields, 'summary'):
        raise Exception("No summary field, add summary in field list", issue.key)
    return str(issue.fields.summary).rstrip().lstrip()

def getFieldList():
    return  [   'summary',
                'status',
                'issuetype',         #issue type
                'customfield_38702', #Item ID
                'customfield_37381', #Feature ID
                'customfield_38698', #Contact Person
                'customfield_38738', #System Spec Start FB
                'customfield_38739', #System Spec End FB
                'customfield_38740', #Entity Spec Start FB
                'customfield_38741', #Entity Spec End FB
                'customfield_38746', #SW Start FB
                'customfield_38747', #SW End FB
                'customfield_38744', #Entity Test Start FB
                'customfield_38745', #Entity Test End FB
                'customfield_38695', #Feature Project Owner
                'customfield_38728', #Release Committed Status
                'customfield_38712', #Requirement Area
                'customfield_38690', # Competence Area
                'customfield_38724', #Planned System Release
                'customfield_38764', #NIDD Impact
                'customfield_39390', #Object Model Expected in FB
                'customfield_39590', #Object Model Param Status
                'customfield_39591', #Object Model Counter Status
                'customfield_39592', #Object Model Fault Status
                'customfield_38753', #sub-activity type,
                'customfield_38750', # Activity Type
                'customfield_38694', # Start FB
                'customfield_38693', # End FB
                'customfield_31591', # Target End
                'customfield_39191', # Sum Original Estimate
                'customfield_39190', # Logged Effort
                'customfield_38710', #Target Release
                'customfield_38705', # FS Status and Date
                'timeoriginalestimate', # Orignal Estimation
                'timespent',            #Time Spent
                'aggregatetimeestimate',#Remaing Effort
                'issuelinks',           #Linked Issues
                'assignee']

def execSearch(url, user, passwd, jql):
    jira = JIRA(server=url, auth=(user, passwd))
    print("Executing JQL search...\n")
    issueList = jira.search_issues(jql, maxResults=0,validate_query=True, fields=getFieldList())
    print("Search completed. Total ", str(issueList.total), " found...\n")
    return issueList

def getCustomFieldValue(issue, fieldName):
    #print(fieldName, ":", issue.raw['fields'][fieldName])
    if str(issue.raw['fields'][fieldName]) == "None":
        value = ""
    else:
        value =issue.raw['fields'][fieldName]['value']
    return value

def getAssignee(issue:Issue):
    if not hasattr(issue.fields, 'assignee'):
        raise Exception("No assignee field for the issue, add assignee in field list")

    if issue.fields.assignee:
        return issue.fields.assignee.displayName
    return ''

def get_assignee(issue:Issue):
    if not hasattr(issue.fields, 'assignee'):
        raise Exception("No assignee field for the issue, add assignee in field list")

    if issue.fields.assignee:
        return issue.fields.assignee.displayName
    return ''

def getAssigneeKey(issue:Issue):
    if hasattr(issue.fields, 'assignee') and issue.fields.assignee:
        return issue.fields.assignee.name
    return ''

def getEffort(effort):
    if str(effort) == "None":
        ret = ""
    else:
        e = int(effort)/3600
        ret = "%d"%e
    return ret

def getContactPerson(issue:Issue):
    #print ("Contact Person:", issue.raw['fields']['customfield_38698'])##
    name = ""
    if issue.raw['fields']['customfield_38698']:
            n = 0
            for c in issue.raw['fields']['customfield_38698']:
                if n == 0:
                    name = c['displayName']
                else:
                    name = name + "," + c['displayName']
                n = n + 1
    return name

def getSfsStartFb(issue:Issue):
    if issue.raw['fields']['customfield_38738']:
        fb = issue.raw['fields']['customfield_38738']
    else:
        fb = ""
    return fb

def getSfsEndFb(issue:Issue):
    if issue.raw['fields']['customfield_38739']:
        fb = issue.raw['fields']['customfield_38739']
    else:
        fb = ""
    return fb

def getEfsStartFb(issue:Issue):
    if issue.raw['fields']['customfield_38740']:
        fb = issue.raw['fields']['customfield_38740']
    else:
        fb = ""
    return fb

def getEfsEndFb(issue:Issue):
    if issue.raw['fields']['customfield_38741']:
        fb = issue.raw['fields']['customfield_38741']
    else:
        fb = ""
    return fb

def getSwStartFb(issue:Issue):
    if issue.raw['fields']['customfield_38746']:
        fb = issue.raw['fields']['customfield_38746']
    else:
        fb = ""
    return fb

def getSwEndFb(issue:Issue):
    if issue.raw['fields']['customfield_38747']:
        fb = issue.raw['fields']['customfield_38747']
    else:
        fb = ""
    return fb

def getEtStartFb(issue:Issue):
    if issue.raw['fields']['customfield_38744']:
        fb = issue.raw['fields']['customfield_38744']
    else:
        fb = ""
    return fb

def getEtEndFb(issue:Issue):
    if issue.raw['fields']['customfield_38745']:
        fb = issue.raw['fields']['customfield_38745']
    else:
        fb = ""
    return fb

def getFpo(issue:Issue):
    #print("Feature Project Owner", issue.raw['fields']['customfield_38695'])
    if issue.raw['fields']['customfield_38695']:
        fpo = issue.raw['fields']['customfield_38695']['displayName']
    else:
        fpo = ""
    return fpo

def get_requirement_area_owner(issue:Issue):
    #print("RAO", issue.raw['fields']['customfield_43891'])
    if issue.raw['fields']['customfield_43891']:
        rao = issue.raw['fields']['customfield_43891']['displayName']
    else:
        rao = ""
    return rao

def get_feature_project_owner(issue:Issue):
    #print("Feature Project Owner", issue.raw['fields']['customfield_38695'])
    if issue.raw['fields']['customfield_38695']:
        fpo = issue.raw['fields']['customfield_38695']['displayName']
    else:
        fpo = ""
    return fpo

def get_fot_leader(issue:Issue):
    #print("FOT Leader", issue.raw['fields']['customfield_38695'])
    if issue.raw['fields']['customfield_38695']:
        fotleader = issue.raw['fields']['customfield_38695']['displayName']
    else:
        fotleader = ""
    return fotleader

def get_priority(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38716'):
        raise Exception('No Bussiness Priority Field, add customfield_38716 in field list', issue.key)
    if issue.raw['fields']['customfield_38716']:
        return int(issue.fields.customfield_38716)
    else:
        return ''

def get_rnd_priority(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38721'):
        raise Exception('No R&D Priority Field, add customfield_38721 in field list', issue.key)
    if issue.raw['fields']['customfield_38716']:
        return int(issue.fields.customfield_38716)
    else:
        return 0

def get_feature_project_owner(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38695'):
        raise Exception("No Feature Project Owner Field, add customfield_38695 in field list", issue.key)

    if issue.raw['fields']['customfield_38695']:
        fpo = issue.fields.customfield_38695.displayName
    else:
        fpo = ''
    return fpo

def get_contact_person(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38698'):
        raise Exception("No contact person field, add customfield_38698 in field list", issue.key)

    contact_person = ''
    if issue.fields.customfield_38698:
        for contact in issue.fields.customfield_38698:
            if contact_person == '':
                contact_person = contact.displayName
            else:
                contact_person = '%s, %s'%(contact_person, contact.displayName)
    return contact_person

def getCommittedStatus(issue:Issue):
    if issue.raw['fields']['customfield_38728']:
        fb = issue.raw['fields']['customfield_38728']['value']
    else:
        fb = ""
    return fb

def getPlannedSystemRelease(issue:Issue):
    rel = ""
    if hasattr(issue.fields,"customfield_38724"):
        if issue.fields.customfield_38724:
            n = 0
            for r in issue.fields.customfield_38724:
                if n == 0:
                    rel = r.value
                else:
                    rel = rel + "," + r.value
                n = n + 1
    return rel

def get_planned_system_release(issue:Issue):
    if not hasattr(issue.fields,"customfield_38724"):
        raise Exception("No Planned System Release Field, add customfield_38724 in field list", issue.key)
    release = ''
    if issue.fields.customfield_38724:
        for r in issue.fields.customfield_38724:
            if release == '':
                release = r.value
            else:
                release = release + "," + r.value
    return release

def updatePlannedSystemRelease(issue:Issue, release:str):
    try:
        issue.update({'customfield_38724': [{'value': release}]})
    except:
        pass

def updateCompetenceArea(issue:Issue, domain:str=''):
    if domain == '':
        domain = get_domain(issue)
    issue.update({'customfield_38690': {'value': DOMAIN_CA_MAP[domain]}})

def updateItemId(issue:Issue, itemid:str):
    issue.update({'customfield_38702':itemid})

def getTargetSystemRelease(issue:Issue):
    if not hasattr(issue.fields, "customfield_38710"):
        raise Exception("No Target Releases Field, add customfield_38710 in field list", issue.key)

    #print(issue.raw['fields']['customfield_38710'])
    if issue.fields.customfield_38710:
        return issue.fields.customfield_38710
    return ''

def get_target_releases(issue:Issue):
    if not hasattr(issue.fields, "customfield_38710"):
        raise Exception("No Target Releases Field, add customfield_38710 in field list", issue.key)

    if issue.fields.customfield_38710:
        return issue.fields.customfield_38710
    else:
        return ''

def getDomainPlanning(issue:Issue):
    domain = get_domain(issue)
    name = getDomainPlanningViaDomainName(domain)

    if name == "":
        name = domain
    return name

def getDomainPlanningViaDomainName(domain):
    domainMap = {
        'OAM':'Bronzini, Patrick (Nokia - FR/Paris-Saclay)',
        'Transport':'Metsala, Esa (Nokia - FI/Espoo)',
        'Cloud':'Zhou, Lan (NSB - CN/Hangzhou)',
        'OAM-Sync':'Huet, Francois (Nokia - FR/Paris-Saclay)',
        'OSS':'Popczynski, Przemyslaw',
        'OAM-Security':'Huet, Francois (Nokia - FR/Paris-Saclay)',
        'SiSo':'Zhou, Xin 3. (NSB - CN/Hangzhou)',
        'SiSo_RU':'Gustrau, Joerg (Nokia - DE/Ulm)',
        'RRM_CP':'Bn, Anupama (Nokia - IN/Bangalore)',
        'RRM_UP':'Godard, Tania (Nokia - FR/Paris-Saclay)',
        'Small Cell':'Dahi, Arezoo (Nokia - US/Naperville)'
    }
    if domain not in domainMap.keys():
        name = ""
    else:
        name=domainMap[domain]
    return name

def getFeatureId(issue:Issue):
    if not hasattr(issue.fields, 'customfield_37381'):
        raise Exception('No Feature ID field, add customfield_37381 in field list')
    return issue.fields.customfield_37381

def get_feature_id(issue:Issue):
    if not hasattr(issue.fields, 'customfield_37381'):
        raise Exception('No Feature ID field, add customfield_37381 in field list')
    if issue.fields.customfield_37381:
        return issue.fields.customfield_37381
    else:
        return ''

def getFeatureIdFromSummary(issue:Issue):
    summary = issue.fields.summary
    pos = summary.find('5GC00')
    if pos >= 0:
        id = summary[pos:pos+9]
    else:
        id = ""
    #print("Feature ID：", id)
    return id

def get_feature_id_from_summary(issue:Issue):
    summary = issue.fields.summary
    reobj = re.compile('^(5GC00[0-9]{4}) (.*)')
    match = reobj.search(summary)
    if not match:
        raise Exception("Unrecognized feature", summary)
    elif len(match.groups()) != 2:
        raise Exception("Unrecognized feature", summary)
    return match.group(1)


def getCfamLeader(issue:Issue):
    feature = getFeatureIdFromSummary(issue)

    if feature == "":
        name = ""
    else:
        name = getCfamLeaderViaFeatureId(feature)
    return name

def getCfamLeaderViaFeatureId(id:str):
    from openpyxl import load_workbook
    from openpyxl import Workbook

    file = getCfamLeaderListFile()

    name = ""
    import os
    if os.path.isfile(file):
        wb = load_workbook(file)
    else:
        print("CFAM Leader List File Not Existing. Run script to generate it at first!")
        return name
    ws = wb['CFAM_Leader']
    n = 2
    while ws.cell(n,1).value:
        if ws.cell(n,1).value == id:
            if ws.cell(n,4).value:
                name = ws.cell(n,4).value
                break
            elif ws.cell(n,3).value:
                name = ws.cell(n,3).value
                break
            elif ws.cell(n,2).value:
                name = ws.cell(n,2).value
                break
        n = n +1
    return name

def getFS1TAStatusViaFeatureId(id):
    return getCfamStatusViaFeatureId("FS1TA", id)

def getCP1StatuViaFeatureId(id):
    return getCfamStatusViaFeatureId("CP1", id)

def get_cp1_status_via_feature_id(jiraobj:Issue, feature_id:str):
    jql = 'issuetype = "Competence Area" AND "sub-activity type" = CP1 AND "Feature ID" ~ "%s"' % feature_id
    print(jql)
    issueList = jiraobj.search_issues(jql, maxResults=1, validate_query=True, fields=['status'])

    print(len(issueList))
    if len(issueList):
        print(issueList[0].fields.status)
        return str(issueList[0].fields.status)
    else:
        return 'New'

def getCfamStatusViaFeatureId(cfam, id):
    cfamStatus = ""

    if cfam == "FS1TA":
        col = 4
    elif cfam =="CP1":
        col = 5
    else:
        print ("Not supported CFAM type ", cfam)
        return

    from openpyxl import load_workbook
    from openpyxl import Workbook

    file = getCfamStatusFile()
    cfamStatus = ""
    import os
    if os.path.isfile(file):
        wb = load_workbook(file)
    else:
        print("CFAM Status File Not Existing. Run script to generate it at first!")
        return cfamStatus

    ws = wb['All']
    n = 2
    while ws.cell(n, 1).value:
        if ws.cell(n,1).value == id:
            cfamStatus = ws.cell(n,col).value
            break
        n = n + 1
    return cfamStatus

def getNiddImpact(issue:Issue):
    if issue.raw['fields']['customfield_38764']:
        info = issue.raw['fields']['customfield_38764']['value']
    else:
        info = ""
    return info

def getExpectFB(issue:Issue):
    if issue.raw['fields']['customfield_39390']:
        expFb = issue.raw['fields']['customfield_39390']['value']
    else:
        expFb = ""
    return expFb

def getCmStatus(issue:Issue):
    cm = str(issue.raw['fields']['customfield_39590'])
    if issue.raw['fields']['customfield_39590']:
        cm = issue.raw['fields']['customfield_39590']['value']
    else:
        cm = ""
    return cm

def getSpecType(issue:Issue):
    specType = ""
    if issue.raw['fields']['customfield_38753']:
        specType = issue.raw['fields']['customfield_38753']['value']

    return str(specType)

def get_specification_type(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38753'):
        raise Exception("No sub-activity type Field, add customfield_38753 in field list")

    if issue.fields.customfield_38753:
        return issue.fields.customfield_38753.value
    return ''

def getFmStatus(issue:Issue):
    fm = str(issue.raw['fields']['customfield_39592'])
    if issue.raw['fields']['customfield_39592']:
        fm = issue.raw['fields']['customfield_39592']['value']
    else:
        fm = ""
    return fm

def getPmStatus(issue:Issue):
    pm = str(issue.raw['fields']['customfield_39591'])
    if issue.raw['fields']['customfield_39591']:
        pm = issue.raw['fields']['customfield_39591']['value']
    else:
        pm = ""
    return pm

def getStartFb(issue:Issue):
    #customfield_38694
    #print("Start FB:",issue.raw['fields']['customfield_38694'])
    if issue.raw['fields']['customfield_38694']:
        fb = str(issue.raw['fields']['customfield_38694'])
    else:
        fb = ""
    return fb

def getEndFb(issue:Issue):
    #customfield_38693
    #print("End FB:",issue.raw['fields']['customfield_38693'])
    if issue.raw['fields']['customfield_38693']:
        fb = str(issue.raw['fields']['customfield_38693'])
    else:
        fb = ""
    return fb

def get_start_fb(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38694'):
        raise Exception('No Start FB Field, add customfield_38694 in field list', issue.key)
    if issue.raw['fields']['customfield_38694']:
        return issue.fields.customfield_38694
    else:
        return ''

def get_end_fb(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38693'):
        raise Exception('No End FB Field, add customfield_38693 in field list', issue.key)
    if issue.raw['fields']['customfield_38693']:
        return issue.fields.customfield_38693
    else:
        return ''


def get_target_end(issue:Issue):
    #print("\n End target: ", issue.fields.customfield_31591)

    if not hasattr(issue.fields, 'customfield_31591'):
        return ''
        #raise Exception('No Target end Field, add customfield_31591 in field list', issue.key)
    if issue.raw['fields']['customfield_31591']:
        return issue.fields.customfield_31591
    else:
        return ''

def get_original_estimate(issue:Issue):
    if not hasattr(issue.fields, 'aggregatetimeoriginalestimate'):
        raise Exception("No aggregatetimeoriginalestimate field, add aggregatetimeoriginalestimate in field list", issue.key)
    if issue.fields.aggregatetimeoriginalestimate:
        return (issue.fields.aggregatetimeoriginalestimate / 3600)
    else:
        return 0

def get_remaining_estimate(issue:Issue):
    if not hasattr(issue.fields, 'timeestimate'):
        raise Exception("No timeestimate field, add timeestimate in field list", issue.key)
    if issue.fields.timeestimate:
        return (issue.fields.timeestimate / 3600)
    else:
        return 0

def getOrgEstimate(issue:Issue):
    ret = getOriginalEstimate(issue)

    if ret:
        return ret
    else:
        return getSumOriginalEstimate(issue)


def getOriginalEstimate(issue:Issue):
    # Original Estimation
    # print(issue.fields.timeoriginalestimate)
    if str(issue.fields.timeoriginalestimate) == "None":
        ret = ""
    else:
        e = int(issue.fields.timeoriginalestimate) / 3600
        ret = "%d" % e
    return ret

def getSumOriginalEstimate(issue:Issue):
    if str(issue.fields.customfield_39191) == "None":
        ret = ""
    else:
        ret = getEffortSum(issue.fields.customfield_39191)
    return ret

def getEffortSum(effort):
    if effort.find('h') >= 0:
        ret = effort.split('h')[0]
    elif effort.find('m') >= 0:
        ret = effort.split('m')[0]
    elif effort.find('w') >= 0:
        ret = effort.split('w')[0]
    else:
        ret = '0'

    if float(ret) == 0:
        ret = ''
    return ret

def getTimeSpentL(issue:Issue):
    # Time Spent
    if not hasattr(issue.fields,'timespent'):
        return ''

    if not issue.fields.timespent:
        return ''

    if int(issue.fields.timespent) != 0:
        e = int(issue.fields.timespent) / 3600
        return "%d" % e
    else:
        return ''


def get_logged_effort(issue:Issue):
    #print(issue.fields.customfield_39190)
    if not hasattr(issue.fields, 'customfield_39190'):
        return ''
    if not issue.fields.customfield_39190:
        return ''

    effort = issue.fields.customfield_39190
    if effort.find('h') >= 0:
        ret = effort.split('h')[0]
    elif effort.find('m') >= 0:
        ret = effort.split('m')[0]
    elif effort.find('w') >= 0:
        ret = effort.split('w')[0]
    else:
        ret = effort

    return ret

def getAggregateTimeSpent(issue:Issue):
    if not hasattr(issue.fields, 'aggregatetimespent'):
        return ''
    if not issue.fields.aggregatetimespent:
        return ''

    if int(issue.fields.aggregatetimespent) != 0:
        e = int(issue.fields.aggregatetimespent) / 3600
        return "%d" % e
    else:
        return ''


def get_aggregate_time_spend(issue:Issue):
    if not hasattr(issue.fields, 'aggregatetimespent'):
        raise Exception('No aggregatetimespent field, add aggregatetimespent in field list', issue.key)
    if not issue.fields.aggregatetimespent:
        return ''
    if int(issue.fields.aggregatetimespent) != 0:
        e = int(issue.fields.aggregatetimespent) / 3600
        return e
    else:
        return ''

def getTimeSpent(issue:Issue):
    if getTimeSpentL(issue) != '':
        return getTimeSpentL(issue)

    if getAggregateTimeSpent(issue) != '':
        return getAggregateTimeSpent(issue)

    if get_logged_effort(issue) != '':
        return get_logged_effort(issue)

def getRemainEffort(issue:Issue):
    # Remaing Effort
    # print(issue.fields.aggregatetimeestimate)
    if str(issue.fields.aggregatetimeestimate) == "None":
        ret = ""
    else:
        e = int(issue.fields.aggregatetimeestimate)/3600
        ret = "%d"%e
    return ret

def get_time_spent_for_quality(issue:Issue):
    if get_aggregate_time_estimate(issue) != '':
        return get_aggregate_time_estimate(issue)

    if get_logged_effort(issue) != '':
        return get_logged_effort(issue)

def get_aggregate_time_estimate(issue:Issue):
    if not hasattr(issue.fields, 'aggregatetimeestimate'):
        raise Exception('No aggregatetimeestimate field, add aggregatetimeestimate in field list', issue.key)

    if issue.fields.aggregatetimeestimate:
        if int(issue.fields.aggregatetimeestimate) != 0:
            return int(issue.fields.aggregatetimeestimate)/3600
    return ''

def getActiveType(issue:Issue):
    # Activity Type
    #print("Active Type:",issue.raw['fields']['customfield_38750'])

    if issue.raw['fields']['customfield_38750']:
        actType= issue.raw['fields']['customfield_38750']['value']
    else:
        actType=""
    return actType

def get_active_type(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38750'):
        raise Exception('No active type field, add customfield_38750 in field list', issue.key)
    if issue.raw['fields']['customfield_38750']:
        actType= issue.raw['fields']['customfield_38750']['value']
    else:
        actType=""
    return actType


def getCompetenceArea(issue:Issue):
    # Competence Area
    #print("Competence Area:",issue.raw['fields']['customfield_38750'])
    if issue.raw['fields']['customfield_38690']:
        ca= issue.raw['fields']['customfield_38690']['value']
    else:
        ca=""
    return ca

def updateActivityType(issue:Issue):
    if isFs1taItem(issue):
        issue.update({'customfield_38750':{'value': ACTIVITY_TYPE_FS1TA}})
    elif isCfamCp1Item(issue) or isCfamCp2Item(issue):
        issue.update({'customfield_38750': {'value': ACTIVITY_TYPE_SFS}})
    else:
        raise Exception('Not a valid A&S CA, key - %s summary - '%(issue.key,issue.fields.summary))

def updateSpecificationType(issue:Issue):
    if isFs1taItem(issue):
        issue.update({'customfield_38753':{'value': SPEC_TYPE_FS1TA}})
    elif isCfamCp1Item(issue):
        issue.update({'customfield_38753': {'value': SPEC_TYPE_CP1}})
    elif isCfamCp2Item(issue):
        issue.update({'customfield_38753': {'value': SPEC_TYPE_CP2}})
    else:
        raise Exception('Not a valid A&S CA, key - %s summary - '%(issue.key,issue.fields.summary))

PATTERN_FS1TA='^(5GC00[0-9]{4})\s{0,1}-\s{0,1}FS1TA[\s{0,1}|-](.*)'
PATTERN_CP1='^(5GC00[0-9]{4})\s{0,1}-\s{0,1}CFAM\s{0,1}-\s{0,1}CP1\s{0,1}[\s{0}|-](.*)'
PATTERN_CP2='^(5GC00[0-9]{4})\s{0,1}-\s{0,1}([A-Y])\s{0,1}-\s{0,1}CFAM\s{0,1}-\s{0,1}CP2\s{0,1}[\s{0}|-](.*)'

def isFs1taItem(issue:Issue):
    summary = issue.fields.summary
    if summary.find('FS1TA') > 0:
        return True
    else:
        return False

def isCfamCp1Item(issue:Issue):
    summary = issue.fields.summary
    if (summary.find('CP1') > 0 and summary.find('CFAM') > 0):
        return True
    else:
        return False

def isCfamCp2Item(issue:Issue):
    summary = issue.fields.summary
    if (summary.find('CP2') > 0 and summary.find('CFAM') > 0):
        return True
    else:
        return False

def isSubFeatureSi(issue:Issue):
    pattern = '^(5GC00[0-9]{4})\s{0,1}-\s{0,1}([A-Y])\s{0,1}[\s{0}|-](.*)'
    if re.compile(pattern).search(issue.fields.summary):
        return True
    else:
        return False

def isFs1taItemS(summary:str):
    reobj = re.compile(PATTERN_FS1TA)
    match = reobj.search(summary)
    if match:
        return True
    else:
        return False

def isCfamCp1ItemS(summary:str):
    reobj = re.compile(PATTERN_CP1)
    match = reobj.search(summary)
    if match:
        return True
    else:
        return False

def isCfamCp2ItemS(summary:str):
    reobj = re.compile(PATTERN_CP2)
    match = reobj.search(summary)
    if match:
        return True
    else:
        return False

def getAssigneeForDomain(domain:str):
    if domain not in DOMAIN_LIST:
        raise Exception("Invalid domain name", domain)
    assigneeList={
        'OAM':'pbronzin',
        'OAM-Sync':'huet6',
        'OAM-Security':'huet6',
        'Cloud':'l14zhou',
        'Transport':'metsala',
        'SC':'qa4439',
        'Small Cell':'qa4439',
        'RRM_CP':'anbn',
        'RRM_UP':'tgodard',
        'SiSo':'xizhou',
        'SiSo_RU':'dems18z4',
        'Performance & Capacity':'tgodard'
    }
    return assigneeList[domain]

def updateAssignee(issue:Issue, domain:str=''):
    if domain == '':
        domain = get_domain(issue)
    name=getAssigneeForDomain(domain)
    if name:
        issue.update({'assignee':{'name': name}})

def update_contact_person(issue:Issue, contact):
    issue.update({'customfield_38698':[{'name': contact}]})

def createNewSystemItem(jira:JIRA, issue:Issue):
    if issue.fields.issuetype.name != ISSUE_TYPE_FT_L:
        raise Exception("Given Issue must be a Customer Feature", issue.fields.issuetype)
    old_childs = getChildItems(jira, jira.issue(issue.key))

    transitions = jira.transitions(issue)
    for t in transitions:
        #print(t['id'],t['name'])
        if t['name'] == 'New SI':
            jira.transition_issue(issue, t['id'])

    new_childs=getChildItems(jira, jira.issue(issue.key))
    for child in new_childs:
        if child not in old_childs:
            return child
    return None


def createNewEntityItem(jira:JIRA, issue:Issue):
    if issue.fields.issuetype.name != ISSUE_TYPE_SI_L:
        raise Exception("Given Issue must be a System Item", issue.fields.issuetype)
    old_childs=getChildItems(jira, jira.issue(issue.key))

    transitions = jira.transitions(issue)
    for t in transitions:
        #print(t['id'],t['name'])
        if t['name'] == 'New EI':
            jira.transition_issue(issue, t['id'])
            break
    new_childs=getChildItems(jira, jira.issue(issue.key))
    for child in new_childs:
        if child not in old_childs:
            return child
    return None

def createNewCAItem(jira:JIRA, issue:Issue):
    if issue.fields.issuetype.name != ISSUE_TYPE_EI_L:
        raise Exception("Given Issue must be a Entity Item", issue.fields.issuetype)
    domain = get_domain(issue)
    if not domain:
        raise Exception('Domain missing', domain)
    #print(getDomainCompetenceArea()[domain])

    old_childs = getChildItems(jira, jira.issue(issue.key))
    transitions = jira.transitions(issue)
    for t in transitions:
        #print(t['id'],t['name'])
        if t['name'] == 'New CA Item':
            jira.transition_issue(issue, t['id'],
                                  fields={'customfield_38690': {'value': DOMAIN_CA_MAP[domain]}})
    new_childs=getChildItems(jira, jira.issue(issue.key))
    for child in new_childs:
        if child not in old_childs:
            return child
    return None

def getFs1taSystemItem(jira:JIRA, featureItem:Issue):
    if featureItem.fields.issuetype.name != ISSUE_TYPE_FT_L:
        raise Exception("Given Issue is not a Customer Feature", featureItem.fields.issuetype.name, featureItem.key)

    childs = getChildItems(jira, featureItem)
    for child in childs:
        if isFs1taItem(child):
            return child
    return None

def getFs1taEntityItem(jira:JIRA, fs1taSi:Issue):
    if fs1taSi.fields.issuetype.name != ISSUE_TYPE_SI_L:
        raise Exception("Given Issue is not a System Item", fs1taSi.fields.issuetype.name, fs1taSi.key)
    childs = getChildItems(jira, fs1taSi)
    for child in childs:
        if isFs1taItem(child):
            return child
    return None

def getFs1taCAItem(jira:JIRA, fs1taEi:Issue):
    if fs1taEi.fields.issuetype.name != ISSUE_TYPE_EI_L:
        raise Exception("Given Issue is not a Entity Item", fs1taEi.fields.issuetype.name, fs1taEi.key)
    childs = getChildItems(jira, fs1taEi)
    for child in childs:
        if isFs1taItem(child):
            return child
    return None

def getItemId(issue:Issue):
    if not hasattr(issue.fields,'customfield_38702'):
        raise Exception("No Item ID field, add customfield_38702 in field list")
    return issue.fields.customfield_38702

def getCp1SystemItem(jira:JIRA, featureItem:Issue):
    if featureItem.fields.issuetype.name != ISSUE_TYPE_FT_L:
        raise Exception("Given Issue is not a Customer Feature", featureItem.fields.issuetype.name, featureItem.key)

    childs = getChildItems(jira, featureItem)
    for child in childs:
        if isCfamCp1Item(child):
            return child
    return None

def getCp1EntityItem(jira:JIRA, cp1Si:Issue):
    if cp1Si.fields.issuetype.name != ISSUE_TYPE_SI_L:
        raise Exception("Given Issue is not a System Item", cp1Si.fields.issuetype.name, cp1Si.key)
    childs = getChildItems(jira, cp1Si)
    for child in childs:
        if isCfamCp1Item(child):
            return child
    return None

def getCp1CaItem(jira:JIRA, cp1Ei:Issue):
    if cp1Ei.fields.issuetype.name != ISSUE_TYPE_EI_L:
        raise Exception("Given Issue is not a Entity Item", cp1Ei.fields.issuetype.name, cp1Ei.key)
    childs = getChildItems(jira, cp1Ei)
    for child in childs:
        if isCfamCp1Item(child):
            return child
    return None

def getIssueTypeShortName(issue:Issue):
    if issue.fields.issuetype.name == ISSUE_TYPE_FT_L:
        return ISSUE_TYPE_FT_S
    elif issue.fields.issuetype.name == ISSUE_TYPE_SI_L:
        return ISSUE_TYPE_SI_S
    elif issue.fields.issuetype.name == ISSUE_TYPE_EI_L:
        return ISSUE_TYPE_EI_S
    elif issue.fields.issuetype.name == ISSUE_TYPE_CA_L:
        return ISSUE_TYPE_CA_S
    else:
        raise Exception("getIssueTypeShortName exception, unsupported issue type", issue.fields.issuetype.name)

def getSubFtSystemItem(jira:JIRA, featureItem:Issue, subFeatureId:str):
    if featureItem.fields.issuetype.name != ISSUE_TYPE_FT_L:
        raise Exception("Given Issue is not a Customer Feature", featureItem.fields.issuetype.name, featureItem.key)

    if re.compile('^[A-Y]{1,2}$').search(subFeatureId) is None:
        raise Exception("Invalid sub-feature Id. Id shall be A~Y", subFeatureId)

    pattern=getFeatureId(featureItem)+"-"+subFeatureId+"\s{0,1}[\s{0}|-].*"
    childs=getChildItems(jira, featureItem)
    for child in childs:
        if re.compile(pattern).search(child.fields.summary):
            return child
    return None

def getSubFtEntityItem(jira:JIRA, systemItem:Issue, subFeatureId:str):
    if systemItem.fields.issuetype.name != ISSUE_TYPE_SI_L:
        raise Exception("Given Issue is not a Customer Feature", systemItem.fields.issuetype.name, systemItem.key)

    if re.compile('^[A-Y]$').search(subFeatureId) is None:
        raise Exception("Invalid sub-feature Id. Id shall be A~Y", subFeatureId)

    pattern=getFeatureId(systemItem)+"-"+subFeatureId+"\s{0,1}[\s{0}|-].*"
    childs=getChildItems(jira, systemItem)
    for child in childs:
        if re.compile(pattern).search(child.fields.summary):
            return child
    return None

def getSubFtCp2EntityItem(jira:JIRA, systemItem:Issue, subFeatureId:str):
    if systemItem.fields.issuetype.name != ISSUE_TYPE_SI_L:
        raise Exception("Given Issue is not a Customer Feature", systemItem.fields.issuetype.name, systemItem.key)

    if re.compile('^[A-Y]{1,2}$').search(subFeatureId) is None:
        raise Exception("Invalid sub-feature Id. Id shall be A~Y", subFeatureId)

    pattern='%s\s{0,1}-\s{0,1}%s\s{0,1}-\s{0,1}CFAM\s{0,1}-\s{0,1}CP2\s{0,1}[\s{0}|-].*'%(getFeatureId(systemItem),subFeatureId)
    childs=getChildItems(jira, systemItem)
    for child in childs:
        if re.compile(pattern).search(child.fields.summary):
            return child
    return None

def getSubFtCp2CaItem(jira:JIRA, entityItem:Issue, subFeatureId:str):
    if entityItem.fields.issuetype.name != ISSUE_TYPE_EI_L:
        raise Exception("Given Issue is not a Entity Item", entityItem.fields.issuetype.name, entityItem.key)

    if re.compile('^[A-Y]{1,2}$').search(subFeatureId) is None:
        raise Exception("Invalid sub-feature Id. Id shall be A~Y", subFeatureId)

    pattern='%s\s{0,1}-\s{0,1}%s\s{0,1}-\s{0,1}CFAM\s{0,1}-CP2\s{0,1}[\s{0}|-].*'%(getFeatureId(entityItem),subFeatureId)
    childs=getChildItems(jira, entityItem)
    for child in childs:
        if re.compile(pattern).search(child.fields.summary):
            return child
    return None

def __CREATE_FS1TA_ITEM_ID(issue:Issue):
    issueType=getIssueTypeShortName(issue)
    if issueType == ISSUE_TYPE_CA_S:
        name="%s-FS1TA"%(getFeatureId(issue))
    else:
        name="%s-FS1TA-%s"%(getFeatureId(issue), getIssueTypeShortName(issue))
    return name

def __CREATE_CP1_ITEM_ID(issue:Issue, domain:str=''):
    issuetype=getIssueTypeShortName(issue)
    if issuetype == ISSUE_TYPE_CA_S:
        if domain == '':
            domain = get_domain(issue)
        name="%s-CFAM-CP1-%s"%(getFeatureId(issue),DOMAIN_CA_MAP_S[domain])
    else:
        name="%s-CFAM-CP1-%s"%(getFeatureId(issue), getIssueTypeShortName(issue))
    return name

def __CREATE_SUB_FEATURE_ITEM_ID(issue:Issue, subFeature:str):
    if subFeature == '':
        raise Exception('Sub-feature must not be empty for sub-feature item', subFeature)

    issuetype=getIssueTypeShortName(issue)

    if issuetype != ISSUE_TYPE_SI_S:
        raise Exception('Only support create system item for sub-feature', issuetype, subFeature)

    name="%s-%s-%s"% (getFeatureId(issue), subFeature, issuetype)
    return name

def __CREATE_CFAM_CP2_ITEM_ID__(issue:Issue, domain:str, subFeature:str):
    if subFeature == '':
        raise Exception('Sub-feature must not be empty for CP2', subFeature)
    issuetype=getIssueTypeShortName(issue)
    if issuetype == ISSUE_TYPE_SI_S:
        raise Exception("Shall not create System Item for CFAM-CP2", issuetype)
    elif issuetype == ISSUE_TYPE_EI_S:
        name="%s-%s-CFAM-CP2-%s"% (getFeatureId(issue), subFeature, issuetype)
    elif issuetype == ISSUE_TYPE_CA_S:
        if domain == '':
            domain = get_domain(issue)
        name="%s-%s-CFAM-CP2-%s"% (getFeatureId(issue), subFeature, DOMAIN_CA_MAP_S[domain])
    return name

def createItemId(issue:Issue, workType:str, domain:str='', subFeature:str=''):
    if (not issue) or (not workType) :
        raise Exception("Empty fields Issue:%s, TYPE:%s"%(issue, workType))
    if workType == WORK_TYPE_FS1TA:
        return __CREATE_FS1TA_ITEM_ID(issue)
    elif workType == WORK_TYPE_CP1:
        return __CREATE_CP1_ITEM_ID(issue, domain)
    elif workType == WORK_TYPE_CP2:
        return __CREATE_CFAM_CP2_ITEM_ID__(issue, domain, subFeature)
    elif workType == WORK_TYPE_SUB:
        return __CREATE_SUB_FEATURE_ITEM_ID(issue, subFeature)
    else:
        raise Exception("Invalid A&S Item Type for the call", workType)
    return ''

def expected_sub_ft_summary(feature:str, sub_feature:str, title:str):
    summary = "%s-%s - %s"%(feature, sub_feature, title)
    return summary

def expected_cp2_item_summary(feature:str, sub_feature:str, title:str):
    summary = "%s-%s-CFAM-CP2 - %s"%(feature, sub_feature, title)
    return summary

def expected_cp1_item_summary(feature:str, title:str):
    summary = "%s-CFAM-CP1 - %s"%(feature, title)
    return summary

def expected_fs1ta_item_summary(feature:str, title:str):
    summary = "%s-FS1TA - %s"%(feature, title)
    return summary

def parse_sub_feature_id(summary:str):
    import re
    match = re.compile('^5GC00[0-9]{4}\s{0,1}-\s{0,1}([A-Z]{1,2})\s{0,1}-{0,1}\s{0,1}(.*)').search(summary)
    if not match:
        return '', ''
    return match.groups()

def expected_activity_type(work_type:str):
    if work_type in [WORK_TYPE_FS1TA]:
        return ACTIVITY_TYPE_FS1TA
    elif work_type in [WORK_TYPE_CP1, WORK_TYPE_CP2]:
        return ACTIVITY_TYPE_SFS
    else:
        raise Exception("INVALID work type given", work_type)

def expected_specification_type(work_type:str):
    if work_type == WORK_TYPE_FS1TA:
        return SPEC_TYPE_FS1TA
    elif work_type == WORK_TYPE_CP1:
        return SPEC_TYPE_CP1
    elif work_type == WORK_TYPE_CP2:
        return SPEC_TYPE_CP2
    else:
        raise Exception("INVALID work type given", work_type)

def getFsStatus(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38705'):
        raise Exception('No FS Status and Date field, add customfield_38705 in field list')
    return issue.fields.customfield_38705

def get_fs_status(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38705'):
        raise Exception('No FS Status and Date field, add customfield_38705 in field list')

    if issue.fields.customfield_38705:
        return issue.fields.customfield_38705
    else:
        return ''

def get_requirement_area(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38712'):
        raise Exception('No Requirement Area field, add customfield_38712 in field list')
    if issue.fields.customfield_38712:
        return issue.fields.customfield_38712
    else:
        return ''

def updateFeatureId(issue:Issue, feature:str):
    if re.compile('^5GC00[0-9]{4}$').search(feature) is None:
        raise Exception('Invalide Feature Id', feature)
    issue.update({'customfield_37381',feature})

def updateDomain(issue:Issue, domain:str):
    if domain not in DOMAIN_LIST:
        raise Exception("Invalid requirement area given", domain)
    issue.update({'customfield_38712': domain})

def update_requirement_area(issue:Issue, requirement_area:str):
    domain = parse_requirement_area(requirement_area)
    if domain.lower() not in domain_list:
        raise Exception('Invalide requirement area', requirement_area)
    issue.update({'customfield_38712': requirement_area})

domain_list={
    'oss'           : 'OSS',
    'oam'           : 'OAM',
    'oam-sync'      : 'OAM-Sync',
    'oam-security'  : 'OAM-Security',
    'oam security'  : 'OAM-Security',
    'cloud'         : 'Cloud',
    'transport'     : 'Transport',
    'rrm'           : 'RRM',
    'rrm_cp'        : 'RRM_CP',
    'rrm cp'        : 'RRM_CP',
    'rrm_up'        : 'RRM_UP',
    'rrm up'        : 'RRM_UP',
    'siso'          : 'SiSo',
    'siso ru'       : 'SiSo_RU',
    'siso_ru'       : 'SiSo_RU',
    'siso_rf'       : 'SiSo_RU',
    'siso rf'       : 'SiSo_RU',
    'siso_rf'       : 'SiSo_RU',
    'sc'            : 'Small Cell',
    'small cell'    : 'Small Cell',
    'small cells'   : 'Small Cell',
    'siso_smallcell': 'Small Cell',
    'siso_airphone' : 'SiSo_Airphone',
    'airphone'      : 'SiSo_Airphone',
    'rrm_airphone'  : 'RRM_AirPhone',
    'transport-security'        : 'Transport-Security',
    'performance & capacity'    : 'Performance & Capacity',
    'capacity & performance'    : 'Performance & Capacity',
    'performance & papacity'    : 'Performance & Capacity',
    'callhandling'  : 'CallHandling',
    'qosenduserexp' : 'QoSEndUserExp',
    'radioperf'     : 'RadioPerf',
    'perfcapa'      : 'PerfCapa',
    'e2eoperability-basic'      : 'E2EOperability-Basic',
    'e2eoperability-sec'        : 'E2EOperability-Sec',
    'e2eoperability-sync'       : 'E2EOperability-Sync',
    'e2eoperability-rnl'       : 'E2EOperability-RNL',
    'e2etrs-basic'              : 'E2ETrs-Basic',
    'e2etrs-sec'    : 'E2ETrs-Sec',
    'bb_hwi'        : 'BB_HWI',
    'ru_hwi'        : 'RU_HWI',
    'smallcells'    : 'SmallCells'
}

def parse_requirement_area(requirement_area:str):
    reobj = re.compile('(FAO .*,){0,1}\s{0,1}A&S\s{0,1}(.*){0,1}')
    match = reobj.search(requirement_area)
    if not match:
        raise Exception('Unrecognized requirement area', requirement_area)
    else:
        return match.groups()[1]

def get_domain(issue:Issue):
    requirement_area = get_requirement_area(issue)

    if not requirement_area:
        return requirement_area

    requirement_area = requirement_area.lstrip().rstrip()
    if requirement_area.find('A&S') >= 0:
        domain = parse_requirement_area(requirement_area)
    elif requirement_area.find('FAO') >= 0 and requirement_area.find('A&S') < 0:
        return ''
    else:
        domain = requirement_area

    if domain.lower() not in domain_list.keys():
        raise Exception('Invalide requirement area', issue.key, domain, requirement_area)

    return domain_list[domain.lower()]

def get_solution_area(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38711'):
        raise Exception('No Requirement Area field, add customfield_38711 in field list')
    if issue.fields.customfield_38711:
        return issue.fields.customfield_38711
    else:
        return ''

def get_fs0_ee(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38737'):
        raise Exception('No FS0 EE field, add customfield_38737 in field list')

    if issue.fields.customfield_38737:
        return (int(issue.fields.customfield_38737))
    else:
        return 0

def get_fs2_ee(issue:Issue):
    if not hasattr(issue.fields, 'customfield_38692'):
        raise Exception('No FS2 EE field, add customfield_38692 in field list')

    if issue.fields.customfield_38692:
        return (int(issue.fields.customfield_38692))
    else:
        return 0

if __name__ == '__main__':
    #import os
    #os.environ['https_proxy']='http://192.168.2.99:9090'
    #os.environ['http_proxy']='http://192.168.2.99:9090'
    url, user, passwd = readConfig()
    jira = JIRA(server=url, auth=(user, passwd))

    issue = jira.issue('FFB-15847')
    print(parse_requirement_area(get_requirement_area(issue)))

    requirement_area = 'A&S SISO'
    print(parse_requirement_area(requirement_area))
    #print(get_fs2_ee(issue))

